/************************************************************************
*
*    File Name: gamewidget.cpp
*    Description: 编写游戏界面，初始化界面（设置图标标题等），添加了血条和得分
*    重写KeyEvent   碰撞检测    玩家移动    背景滚动    子弹移动       player发射子弹
*    敌机爆炸    插入数据库    敌机移动
*    Version: V2.0
*    Author: 王涵
*    Create Time: 2024-11-27
*
*************************************************************************/
#include "gamewidget.h"
#include "ui_gamewidget.h"

GameWidget::GameWidget(int map_path,int plane_path,QWidget *parent) :
    QWidget(parent),
    ui(new Ui::GameWidget)
{
    ui->setupUi(this);
    // 初始化界面
    this->resize(GAME_WIDTH,GAME_HEIGHT);
    this->setWindowTitle(GAME_TITLE);
    this->setWindowIcon(QIcon(GAME_ICON));
    this->map_path = map_path;
    this->plane_path = plane_path;
    scene = new QGraphicsScene(0,0,GAME_WIDTH,GAME_HEIGHT,this); // 创建场景
    view = new QGraphicsView(scene,this); // 显示场景

    create_map();
    create_player_plane();

    // 血条
    blood_bar = new QProgressBar(this);
    blood_bar->setGeometry(GAME_WIDTH - 150,GAME_HEIGHT - 100,100,20);
    blood_bar->setStyleSheet(
                "QProgressBar::chunk {"
                "   background-color: red;"
                "   width: 20px;"
                "}"
                );
    blood_bar->setMinimum(0);
    blood_bar->setMaximum(100);
    blood_bar->setValue(100);
    blood_bar->setTextVisible(false);
    blood_bar->move(GAME_WIDTH - 150,GAME_HEIGHT - 100);

    // 得分
    score = 0;
    score_label = new QLabel(this);
    score_label->setGeometry(GAME_WIDTH - 150,GAME_HEIGHT - 120,150,120);
    score_label->setStyleSheet(
                "font-size : 25px;"
                "color : black"
                );
    score_label->setText("得分 : 0");

    // create敌机timer
    enemy_timer = new QTimer(this);
    connect(enemy_timer,&QTimer::timeout,this,&GameWidget::createEnemies);
    enemy_timer->start(1000);
    // 碰撞检测timer1
    collision_timer1 = new QTimer(this);
    connect(collision_timer1,&QTimer::timeout,this,&GameWidget::checkCollisions1);
    collision_timer1->start(16);
    // 碰撞检测timer2
    collision_timer2 = new QTimer(this);
    connect(collision_timer2,&QTimer::timeout,this,&GameWidget::checkCollisions2);
    collision_timer2->start(16);
    // 背景滚动timer
    background_move_timer = new QTimer(this);
    connect(background_move_timer, &QTimer::timeout, this, &GameWidget::background_move_timer_slot);
    background_move_timer->start(16);
}

GameWidget::~GameWidget()
{
    delete ui;
    delete enemy_timer;
    delete collision_timer1;
    delete  collision_timer2;
    delete  background_move_timer;
    qDeleteAll(scene->items());
    delete scene;
    delete view;
}
/*************************重写KeyEvent********************************
*
*    函 数 名：void play_page::keyPressEvent(QKeyEvent *event);
*                    void play_page::keyReleaseEvent(QKeyEvent *event);
*    函数功能：重写KeyEvent    Press   Release
*    返 回 值:  void
*
*    作    者：王涵
*    创建时间：2024-11-25
*
************************************************************************/
void GameWidget::keyPressEvent(QKeyEvent *event)
{
    if(event->key() == Qt::Key_W)   player_plane->setup(1);
    else if(event->key() == Qt::Key_S)  player_plane->setdown(1);
    else if(event->key() == Qt::Key_A)  player_plane->setleft(1);
    else if(event->key() == Qt::Key_D)  player_plane->setright(1);
    else    QWidget::keyPressEvent(event);
}
void GameWidget::keyReleaseEvent(QKeyEvent *event)
{
    if(event->key() == Qt::Key_W)   player_plane->setup(0);
    else if(event->key() == Qt::Key_S)  player_plane->setdown(0);
    else if(event->key() == Qt::Key_A)  player_plane->setleft(0);
    else if(event->key() == Qt::Key_D)  player_plane->setright(0);
    else if(event->key() == Qt::Key_J)  player_plane->shoot(scene);//发射子弹
    else    QWidget::keyReleaseEvent(event);
}
/*************************碰撞检测************************************
*
*    函 数 名：void GameWidget::checkCollisions1()
*                     void GameWidget::checkCollisions2()
*    函数功能：碰撞检测,两个函数分别检测敌机撞玩家和子弹打敌机
*    返 回 值:  void
*
*    作    者：王涵
*    创建时间：2024-11-30
*
************************************************************************/
void GameWidget::checkCollisions1()
{
    QList<QGraphicsItem*> items = scene->items();// 获取场景中的所有项
    // 检测敌机与玩家的碰撞
    foreach(QGraphicsItem *item,items){
        if(!flag){ // 如果玩家已经死亡就不再进行检测
            EnemyPlane *enemy = dynamic_cast<EnemyPlane*>(item);
            if(enemy && player_plane->collidesWithItem(enemy)){
                connect(enemy,&EnemyPlane::destroyed,this,&GameWidget::create_bomb);
                emit enemy->destroyed(enemy->pos().x(),enemy->pos().y()); // 销毁敌机
                scene->removeItem(enemy); // 移除敌机贴图
                delete enemy;

                // 扣除生命值
                player_plane->blood -= ENEMY_DAMAGE;
                blood_bar->setValue(player_plane->blood); // 血条减少
                score -= 10; // 掉血
                if(score < 0)   score = 0; // 最低0分
                score_label->setText(QString("得分 : %1").arg(QString::number(score)));
                if(player_plane->blood <= 0){
                    flag = 1;
                    scene->removeItem(player_plane);
                    delete player_plane;
                    QMessageBox::critical(this,"GAME OVER",QString("你的飞机被摧毁了,您的得分是 %1 ").arg(QString::number(score)));
                    void insert_data();
                    emit game_close();
                }
            }
        }
    }
}
void GameWidget::checkCollisions2(){
    QList<QGraphicsItem*> items = scene->items();// 获取场景中的所有项
    // 检测子弹与敌机的碰撞
    foreach(QGraphicsItem *item,items){
        Bullet *bullet = dynamic_cast<Bullet*>(item);
        if(bullet)
            foreach(QGraphicsItem *otherItem,items){
                EnemyPlane *enemy = dynamic_cast<EnemyPlane*>(otherItem);
                if(enemy && bullet->collidesWithItem(enemy)){
                    connect(enemy,&EnemyPlane::destroyed,this,&GameWidget::create_bomb);
                    emit enemy->destroyed(enemy->pos().x(),enemy->pos().y()); // 销毁敌机
                    scene->removeItem(bullet);
                    delete bullet;
                    scene->removeItem(enemy);
                    delete enemy;
                    score += 5;
                    score_label->setText(QString("得分 : %1").arg(QString::number(score)));
                    break;
                }
            }
    }
}
/*************************玩家移动***********************************
*
*    函 数 名：void GameWidget::planeMoveTimerSlot()
*    函数功能：玩家移动(与KeyEvent连接)
*    返 回 值:  void
*
*    作    者：王涵
*    创建时间：2024-11-26
*
************************************************************************/
void PlayerPlane::player_plane_move()
{
    double planeX,planeY;
    int speed = PLANE_SPEED;
    planeX = this->x();
    planeY = this->y();
    planeX += left?-speed:0 + right?speed:0;
    planeY += up?-speed:0 + down?speed:0;
    if(planeX <0)   planeX = 0;
    if(planeX > GAME_WIDTH - 0.5 * PLANE_WIDTH) planeX = GAME_WIDTH - 0.5 * PLANE_WIDTH;
    if(planeY < 0)  planeY = 0;
    if(planeY > GAME_HEIGHT - PLANE_HEIGHT) planeY = GAME_HEIGHT - PLANE_HEIGHT;
    this->setPos(planeX,planeY);
}
/*************************背景滚动***********************************
*
*    函 数 名：void GameWidget::planeMoveTimerSlot()
*    函数功能：背景滚动(与timer连接)
*    返 回 值:  void
*
*    作    者：王涵
*    创建时间：2024-11-26
*
************************************************************************/
void GameWidget::background_move_timer_slot(){
    back_ground->background_1_y += back_ground->background_speed;
    if( back_ground->background_1_y >= GAME_HEIGHT)  back_ground->background_1_y = -GAME_HEIGHT;
    back_ground->background_2_y +=  back_ground->background_speed;
    if( back_ground->background_2_y >= GAME_HEIGHT)  back_ground->background_2_y = -GAME_HEIGHT;
    back_ground->set_pos();
}
/*************************子弹移动***********************************
*
*    函 数 名：void Bullet::Bullet_Move()
*    函数功能：子弹移动（timer）
*    返 回 值:  void
*
*    作    者：王涵
*    创建时间：2024-11-26
*
************************************************************************/
void Bullet::bullet_move()
{
    setPos(x(),y() - BULLET_SPEED);// 子弹移动
    // 越界删除
    if(pos().y() <= -BULLET_HEIGHT){
        scene()->removeItem(this);
        delete  this;
    }
}
/*************************player发射子弹***********************************
*
*    函 数 名：void PlayerPlane::shoot(QGraphicsScene *scene)
*    函数功能：发射子弹(KeyEvent)
*    返 回 值:  void
*
*    作    者：王涵
*    创建时间：2024-11-26
*
************************************************************************/
void PlayerPlane::shoot(QGraphicsScene *scene)
{
    // 创建子弹
    Bullet *bullet = new Bullet();
    // 设置子弹的初始位置
    bullet->setPos(pos().x()+PLANE_WIDTH/2-10,pos().y());
    // 将子弹添加到场景中
    scene->addItem(bullet);
}
/*************************敌机移动***********************************
*
*    函 数 名：void EnemyPlane::enemy_plane_move()
*    函数功能：敌机移动(连接计时器)
*    返 回 值:  void
*
*    作    者：王涵
*    创建时间：2024-11-26
*
************************************************************************/
void EnemyPlane::enemy_plane_move(){
    setPos(x(),y() + ENEMY_SPEED);
    if(pos().y() > GAME_HEIGHT){
        scene()->removeItem(this);
        delete this;
    }
}
/*************************敌机爆炸***********************************
*
*    函 数 名：void EnemyPlane::enemy_bomb()
*    函数功能：敌机爆炸
*    返 回 值:  void
*
*    作    者：王涵
*    创建时间：2024-11-26
*
************************************************************************/
void GameWidget::create_bomb(double b_x,double b_y)
{
    Bomb *bombs = new Bomb(this);
    //设置起始位置
    bombs->setPos(b_x,b_y);
    //添加到场景
    scene->addItem(bombs);
    QTimer *timer = new QTimer(this);
    connect(timer,&QTimer::timeout,this,[=](){
        scene->removeItem(bombs);
        delete  bombs;
        // 停止计时器
        timer->stop();
        // 清理计时器
        timer->deleteLater();
    });
    timer->start(100);
}
/*************************create plane***********************************
*
*    函 数 名：void GameWidget::create_player_plane()
*    函数功能：create plane(连接计时器)
*    返 回 值:  void
*
*    作    者：王涵
*    创建时间：2024-11-26
*
************************************************************************/
void GameWidget::create_player_plane()
{
    player_plane = new PlayerPlane(this);// 创建我的飞机
    player_plane->picture_choose(plane_path);
    player_plane->setPos(PLANE_X,PLANE_Y);// 设置起始位置
    scene->addItem(player_plane);// 添加到场景
}
/*************************create map***********************************
*
*    函 数 名：void GameWidget::create_map()
*    函数功能：create map(连接计时器)
*    返 回 值:  void
*
*    作    者：王涵
*    创建时间：2024-11-26
*
************************************************************************/
void GameWidget::create_map()
{
    back_ground = new Map;
    back_ground->picture_choose(map_path);
    back_ground->background_item_1 = scene->addPixmap(back_ground->background_1);
    back_ground->background_item_2 = scene->addPixmap(back_ground->background_2);
}
/*************************create敌机***********************************
*
*    函 数 名：void GameWidget::createEnemies()
*    函数功能：create敌机(连接计时器)
*    返 回 值:  void
*
*    作    者：王涵
*    创建时间：2024-11-26
*
************************************************************************/
void GameWidget::createEnemies()
{
    EnemyPlane *enemy = new EnemyPlane(); //创建敌机
    enemy->setPos(QRandomGenerator::global()->bounded(0,GAME_WIDTH-ENEMY_WIDTH),0); // 设置敌机的位置
    scene->addItem(enemy); // 将敌机添加到场景中
}
/*************************数据库插入数据***********************************
*
*    函 数 名：void GameWidget::insert_data(QString user_name)
*    函数功能：连接数据库，插入数据
*    返 回 值:  void
*    备注：未实现数据更新功能
*    作    者：王涵
*    创建时间：2024-11-27
*
************************************************************************/
void GameWidget::insert_data(QString user_name){
    db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName("war_plane.db");
    db.open();
    query = new QSqlQuery;
    //query->exec("DELETE  FROM score_board");
    if(query->exec(QString("SELECT score  FROM score_board WHERE user_name = '%1')").arg(user_name))){ // 已经存在该用户的记录
        int old_score = query->value("score").toInt();
        qDebug()<<score;
        qDebug()<<user_name;
        qDebug()<<old_score;
        if(score > old_score){
            query->exec(QString("UPDATE score_board SET score = %1 WHERE user_name = '%2'").arg(score).arg(user_name));
        }
    }
    else{
        query->exec(QString("INSERT INTO  score_board VALUES('%1',%2)").arg(user_name).arg(score)); // 重新插入数据
    }

}
